package com.briup.util;


import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Classname QRCodeUtils
 * @Description 二维码生成工具类
 */
@Slf4j
public class QRCodeUtils {
    /**
     * 生成普通二维码
     *
     * @param content 内容
     * @param width   宽度
     * @param height  高度
     * @param format  生成二维码文件格式
     * @param target  生成二维码文件的目标地址
     * @throws IOException IO异常
     */
    public static void generateQRCode(String content,int width,int height,String format,String target) throws IOException, WriterException {
        //创建二维码相关创建矩阵信息（边距、字符集编码）存放在Map<EncodeHintType, Object>集合中
        Map<EncodeHintType, Object> hints = buildEncodeHintTypeMap();
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        //输出二维码
        MatrixToImageWriter.writeToPath(bitMatrix, format, new File(target).toPath());
    }


    /**
     * 生成Logo图标的二维码
     *
     * @param content 内容
     * @param width   宽度
     * @param height  高度
     * @param format  生成二维码文件格式
     * @param logoTarget  logo文件目标地址
     * @param target  生成二维码文件的目标地址
     * @throws IOException     IO异常
     * @throws WriterException 编写器异常
     */
    public static String generateLogoQRCode(String content,int width,int height,String format,String logoTarget,String target) throws IOException, WriterException {
        //创建二维码相关创建矩阵信息（边距、字符集编码）存放在Map<EncodeHintType, Object>集合中
        Map<EncodeHintType, Object> hints = buildEncodeHintTypeMap();
        //创建矩阵信息对象
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        /*
            问题：生成二维码正常,生成带logo的二维码logo变成黑白
            原因：MatrixToImageConfig默认黑白，需要设置BLACK、WHITE
         */
        MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
        BufferedImage bufferedImage = LogoMatrix(MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig), new File(logoTarget));
        //创建文件
        File file = new File(target);
        //输出二维码
        ImageIO.write(bufferedImage, format, file);
        //返回文件名称
        return file.getName();
    }


    /**
     * 二维码解析器
     *
     * @param file 待扫描二维码文件
     * @throws IOException       IO异常
     * @throws NotFoundException 未找到异常
     */
    public static void QRReader(File file) throws IOException, NotFoundException {
        //创建MultiFormatReader读取二维码
        MultiFormatReader formatReader = new MultiFormatReader();
        //读取指定的二维码文件
        BufferedImage bufferedImage = ImageIO.read(file);
        BinaryBitmap binaryBitmap= new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(bufferedImage)));
        //定义二维码参数
        Map hints= new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        Result result = formatReader.decode(binaryBitmap, hints);
        //输出相关的二维码信息
        log.info("==========解析成功==========");
        log.info("解析结果：{}",result.toString());
        log.info("二维码格式类型：{}",result.getBarcodeFormat());
        log.info("二维码文本内容：{}",result.getText());
        //刷新流
        bufferedImage.flush();
    }


    /**
     * 二维码添加logo
     *
     * @param matrixImage 源二维码图片
     * @param logoFile    logo 文件
     * @return {@link BufferedImage} 返回带有logo的二维码图片
     * @throws IOException IO异常
     */
    public static BufferedImage LogoMatrix(BufferedImage matrixImage, File logoFile) throws IOException{
        /**
         * 读取二维码图片，并构建绘图对象
         */
        Graphics2D graphics = matrixImage.createGraphics();

        int matrixWidth = matrixImage.getWidth();
        int matrixHeight = matrixImage.getHeight();

        /**
         * 读取Logo图片
         */
        BufferedImage logo = ImageIO.read(logoFile);

        //开始绘制图片
        graphics.drawImage(logo,matrixWidth/5*2,matrixHeight/5*2, matrixWidth/5, matrixHeight/5, null);//绘制
        BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
        graphics.setStroke(stroke);// 设置笔画对象
        //指定弧度的圆角矩形
        RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth/5*2, matrixHeight/5*2, matrixWidth/5, matrixHeight/5,20,20);
        graphics.setColor(Color.white);
        graphics.draw(round);// 绘制圆弧矩形

        //设置logo 有一道灰色边框
        BasicStroke stroke2 = new BasicStroke(1,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
        graphics.setStroke(stroke2);// 设置笔画对象
        RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth/5*2+2, matrixHeight/5*2+2, matrixWidth/5-4, matrixHeight/5-4,20,20);
        graphics.setColor(new Color(128,128,128));
        graphics.draw(round2);// 绘制圆弧矩形

        graphics.dispose();
        matrixImage.flush() ;
        return matrixImage ;
    }

    /**
     * 创建二维码相关创建矩阵信息（边距、字符集编码）存放在Map<EncodeHintType, Object>集合中
     *
     * @return {@link Map}<{@link EncodeHintType}, {@link Object}>
     */
    public static Map<EncodeHintType, Object> buildEncodeHintTypeMap(){
        Map<EncodeHintType, Object> hints = new HashMap<>();
        //内容编码格式
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 指定纠错等级
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        //设置二维码边的空度，非负数
        hints.put(EncodeHintType.MARGIN, 1);
        return hints;
    }
}